/***************************

mc

Function description:
  mex version of mc 
  motion compensation
  support 
  1. temp interp (P+C)/2 
  2. obmc
  3. cuc mc
  4. logo
  5. oob

  parameter : 
              cur_pic(UINT8 YUV[]),
			  cur_polarity()
              pre_pic(UINT8 YUV[]),
			  pic_pola, (PIC_POLARITY: prog(0), top(1), bot(2)),
			  chrom_type, (CHROMA: 422, 444, 420, 422)
			  mc_parameter (STRUCT)

  return    : out_pic (UINT8 YUV[])

Version number: 1.0

Editor: source insight 3.1

Data : 2010-06-10

Author: Wang Dong

****************************/


#include <math.h>
#include "mex.h"
//#include "portability.h"
typedef unsigned char     UINT8;
typedef char              INT8;
typedef unsigned short    UINT16;
typedef short             INT16;
typedef int               INT32;
typedef unsigned int      UINT32;
typedef enum 
{
	FRM_PARITY_PROGRESS     = 0,
	FRM_PARITY_TOP          = 1,
	FRM_PARITY_BOTTOM       = 2
} T_FRM_PARITY;


typedef struct
{
   INT16    vector[2];
   UINT16	penalty;
   UINT8    type;
}  T_CAND_VEC;

#undef _INCLUDE_

#ifdef 		    _DEBUG_
#define 		_DEBUG_PRED_VECTOR
#define 		_DEBUG_GET_CURRENT_BLOCK
#define 		_DEBUG_GET_REF_BLOCK
#define 		_DEBUG_CALC_BLK_ERR
#define 		_DEBUG_UPDATE_MV
#define 		_DEBUG_3DR_ME
#else
#define         mexPrintf   //
#endif
#define MAX_BLK_SIZE_X             64
#define MAX_BLK_SIZE_Y             64
//input parameters declare
//data path input
#define PREVIOUS_YUV                prhs[0]
#define PRE_POLARITY                prhs[1]
#define CURRENT_YUV                 prhs[2]
#define CUR_POLARITY                prhs[3]
//mc parameters
#define MC_PARAMETER                prhs[4]

//output parameters declare
#define MC_RESULT                   plhs[0]



typedef struct 
{
	UINT8      temp_phase;      //64 totally, 0 @previous, 64 @ current
	UINT8      block_size[2];
	UINT16     block_number[2];
	INT16*     vector;
	UINT8      vec_precision[2];
	//obmc
	bool       obmc_en;
	UINT16     obmc_vardiff_thr;
	UINT8      obmc_vardiff_trans;
	//refine
	bool       refine_en;
	bool       refine_dir_en;
	bool       refine_cent_only;
	UINT8      refine_vardiff_thr;
	UINT8      refine_length;
	UINT8      refine_dir_minvec_th;
	UINT8      refine_dir_mindiff_th;
	UINT8      refine_dir_maxdiff_th;
	//cuc
	bool       cuc_en;         //
	UINT8      cuc_low_cnt_thr;
	UINT8      cuc_hi_cnt_thr;
	bool       cuc_alpha_en;
	//logo
	bool       logo_en;
    UINT8      logo_hit_range[2];
	UINT8      logo_ext_range[2];
    bool       logo_tuning_vec_en;
    //oob protect
	bool       oob_en;
	UINT16     oob_vec_range[2];
    //
	INT8*      cuc_mask;        //mask cuc mask: int8, -1: cover; 1 uncover; 7 CUC conflict; 5: bad vector; 3:good vector 
	UINT8*     logo_mask;       //mask of logo
	UINT16     window[4];       //0:4  l_x, r_x, t_y, b_y, counter from 0
	//output selector
	UINT8      out_sel;         //0: (p+c)/2;  1: p0; 2:c0; 3:(p0+c0)/2; 
	//
	bool       good_prot_en;
	bool       bad_prot_en;
    UINT8      y_overlay_mode;
    UINT8      uv_overlay_mode;
    INT8       ol_ku;
	INT8       ol_kv;
	bool       grid_en;
} T_MC_PARAM;




void   verify_common_parameters (    UINT16 iCurSize[2], int iCurPolarity,
		                             UINT16 iPreSize[2], int iPrePolarity)
{
    
    return;
}



void   parser_mc_parameter(T_MC_PARAM* pMCParam, const mxArray* pmxaMCParam)
{

	char         sTempPhase    [32] = "temp_phase";
	char         sBlkSz        [32] = "block_size";
    char         sBlkNum       [32] = "block_number";
	char         sVector       [32] = "vector";
	char         sVecPrecision [32] = "vec_precision";
    char         sCUCMask      [32] = "cuc_mask";
    char         sLogoMask     [32] = "logo_mask";
    char         sWindow       [32] = "window";
	//obmc
	char         sOBMCEn       [32] = "obmc_en";
	char         sOBMCVDiffTh  [32] = "obmc_vardiff_thr";
	char         sOBMCVDiffTran[32] = "obmc_vardiff_trans";
	//refine
	char         sRefineEn     [32] = "refine_en";
	char         sRefineDirEn  [32] = "refine_dir_en";
	char         sRefineCtOnly [32] = "refine_cent_only";
	char         sRefineVDiffTh[32] = "refine_vardiff_thr";
	char         sRefineLength [32] = "refine_length";
	char         sRefineDirMinVecTh [32] = "refine_dir_minvec_th";  //UINT8      refine_dir_minvec_th;
	char         sRefineDirMinDiffTh[32] = "refine_dir_mindiff_th"; //UINT8      refine_dir_mindiff_th;
	char         sRefineDirMaxDiffTh[32] = "refine_dir_maxdiff_th"; //UINT8      refine_dir_maxdiff_th;
	//cuc
	char         sCUCEn        [32] = "cuc_en";
	char         sCUCLowCntTh  [32] = "cuc_low_cnt_thr";
	char         sCUCHiCntTh   [32] = "cuc_hi_cnt_thr";
	char         sCUCAlphaEn   [32] = "cuc_alpha_en";
	//logo
	char         sLogoEn       [32] = "logo_en";
    char         sLogoHitRange [32] = "logo_hit_range";
	char         sLogoExtRange [32] = "logo_ext_range"; //UINT8      logo_ext_range[2];

	char         sLogoTuneVEn  [32] = "logo_tuning_vec_en";
    //ob
	char         sOOBEn        [32] = "oob_en";
	char         sOOBVecRange  [32] = "oob_vec_range";
	//out mux
	char         sOutSel       [32] = "out_sel";//	UINT8      out_sel;         //0: (p+c)/2;  1: p0; 2:c0; 3:(p0+c0)/2; 
	char         sGoodProtEn   [32] = "good_prot_en"; //bool       good_prot_en;
	char         sBadProtEn    [32] = "bad_prot_en"; //bool       bad_prot_en;
    char         sYOverlayMode [32] = "y_overlay_mode"; //UINT8      y_overlay_mode;
    char         sUVOverlayMode[32] = "uv_overlay_mode"; //UINT8      uv_overlay_mode;
    char         sOlKu         [32] = "ol_ku"; //INT8       ol_ku;
	char         sOlKv         [32] = "ol_kv"; //INT8       ol_kv;
	char         sGridEn       [32] = "grid_en"; //bool       grid_en;


    //int          iIdx;
    mxArray *    pmxaTemp;
    UINT8*       pui8Temp;
    INT8*        pi8Temp;
    UINT16*      pui16Temp;
    INT16*       pi16Temp;
    
    mexPrintf("parser mc parameters\n");



	//get temp phase
	pmxaTemp = mxGetField(pmxaMCParam, 0, sTempPhase);
	pui8Temp = (UINT8*)mxGetData(pmxaTemp);
	pMCParam->temp_phase    =   pui8Temp[0];

    //get block size
    pmxaTemp = mxGetField(pmxaMCParam, 0, sBlkSz);
    pui8Temp = (UINT8*)mxGetData(pmxaTemp);
    pMCParam->block_size[0]  =  pui8Temp[0];
    pMCParam->block_size[1]  =  pui8Temp[1];
    mexPrintf("block_size %d,%d\n", pMCParam->block_size[0], pMCParam->block_size[1]);

    //get block number
    pmxaTemp = mxGetField(pmxaMCParam, 0, sBlkNum);
    pui16Temp = (UINT16*)mxGetData(pmxaTemp);
    pMCParam->block_number[0]  =  pui16Temp[0];
    pMCParam->block_number[1]  =  pui16Temp[1];
    mexPrintf("block_number %d,%d\n", pMCParam->block_number[0], pMCParam->block_number[1]);

    //get vector
    pmxaTemp = mxGetField(pmxaMCParam, 0, sVector);
    pi16Temp = (INT16*)  mxGetData(pmxaTemp);
    pMCParam->vector  = pi16Temp;
	mexPrintf("vector: @%H\n", pMCParam->vector);

	//get vector precision
	pmxaTemp = mxGetField(pmxaMCParam, 0, sVecPrecision);
	pui8Temp = (UINT8*)mxGetData(pmxaTemp);
	pMCParam->vec_precision[0]  =  1<<pui8Temp[0];
	pMCParam->vec_precision[1]  =  1<<pui8Temp[1];
	mexPrintf("block_number %d,%d\n", pMCParam->block_number[0], pMCParam->block_number[1]);

	//get cuc_mask
	pmxaTemp = mxGetField(pmxaMCParam, 0, sCUCMask);
	pi8Temp = (INT8*)  mxGetData(pmxaTemp);
	pMCParam->cuc_mask  = pi8Temp;
	mexPrintf("cuc_mask: @%H\n", pMCParam->cuc_mask);

	//get logo_mask
	pmxaTemp = mxGetField(pmxaMCParam, 0, sLogoMask);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->logo_mask  = pui8Temp;
	mexPrintf("logo_mask: @%H\n", pMCParam->logo_mask);

	//get window
	pmxaTemp = mxGetField(pmxaMCParam, 0, sWindow);
	pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pMCParam->window[0]  = pui16Temp[0];//tl_x  unit block
	pMCParam->window[1]  = pui16Temp[1];//tl_y  unit block
	pMCParam->window[2]  = pui16Temp[2];//width unit block
	pMCParam->window[3]  = pui16Temp[3];//height unit block
	mexPrintf("window_start: [ %d, %d]\n       width: %d\n      heitht: %d", 
			  pMCParam->window[0], pMCParam->window[1], pMCParam->window[2], pMCParam->window[3]);

	//get obmc_en
    pmxaTemp = mxGetField(pmxaMCParam, 0, sOBMCEn);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->obmc_en  = (pui8Temp[0]!=0);
	mexPrintf("obmc_en : %d\n  ", pMCParam->obmc_en);
	//get obmc_vardiff_thr
    pmxaTemp = mxGetField(pmxaMCParam, 0, sOBMCVDiffTh);
    pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pMCParam->obmc_vardiff_thr  = pui16Temp[0];
	mexPrintf("obmc_vardiff_thr : %d\n  ", pMCParam->obmc_vardiff_thr);
	//get obmc_vardiff_trans
    pmxaTemp = mxGetField(pmxaMCParam, 0, sOBMCVDiffTran);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->obmc_vardiff_trans  = pui8Temp[0];
	mexPrintf("obmc_vardiff_trans : %d\n  ", pMCParam->obmc_vardiff_trans);

	//get refine_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_en  = (pui8Temp[0]!=0);
	mexPrintf("refine_en : %d\n  ", pMCParam->refine_en);
	//get refine_dir_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineDirEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_dir_en  = (pui8Temp[0]!=0);
	mexPrintf("refine_dir_en : %d\n  ", pMCParam->refine_dir_en);
	//get refine_cent_only
	pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineCtOnly);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_cent_only  = (pui8Temp[0]!=0);
	mexPrintf("refine_cent_only : %d\n  ", pMCParam->refine_cent_only);
	//get refine_vardiff_thr
    pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineVDiffTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_vardiff_thr  = pui8Temp[0];
	mexPrintf("refine_vardiff_thr : %d\n  ", pMCParam->refine_vardiff_thr);
	//get refine_length
    pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineLength);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_length  = pui8Temp[0];
	mexPrintf("refine_length : %d\n  ", pMCParam->refine_length);
	//get refine_dir_minvec_th
    pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineDirMinVecTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_dir_minvec_th  = pui8Temp[0];
	mexPrintf("refine_dir_minvec_th : %d\n  ", pMCParam->refine_dir_minvec_th);	         
	//get refine_dir_mindiff_th
    pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineDirMinDiffTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_dir_mindiff_th  = pui8Temp[0];
	mexPrintf("refine_dir_mindiff_th : %d\n  ", pMCParam->refine_dir_mindiff_th);	
	//get refine_dir_maxdiff_th
    pmxaTemp = mxGetField(pmxaMCParam, 0, sRefineDirMaxDiffTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->refine_dir_maxdiff_th  = pui8Temp[0];
	mexPrintf("refine_dir_maxdiff_th : %d\n  ", pMCParam->refine_dir_maxdiff_th);	

	
	
	//get cuc_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sCUCEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->cuc_en  = (pui8Temp[0]!=0);
	mexPrintf("cuc_en : %d\n  ", pMCParam->cuc_en);
	//get cuc_low_cnt_thr
    pmxaTemp = mxGetField(pmxaMCParam, 0, sCUCLowCntTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->cuc_low_cnt_thr  = pui8Temp[0];
	mexPrintf("cuc_low_cnt_thr : %d\n  ", pMCParam->cuc_low_cnt_thr);
	//get cuc_hi_cnt_thr
    pmxaTemp = mxGetField(pmxaMCParam, 0, sCUCHiCntTh);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->cuc_hi_cnt_thr  = pui8Temp[0];
	mexPrintf("cuc_hi_cnt_thr : %d\n  ", pMCParam->cuc_hi_cnt_thr);
	//get cuc_alpha_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sCUCAlphaEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->cuc_alpha_en  = (pui8Temp[0]!=0);
	mexPrintf("cuc_alpha_en : %d\n  ", pMCParam->cuc_alpha_en);


	//get logo_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sLogoEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->logo_en  = (pui8Temp[0]!=0);
	mexPrintf("logo_en : %d\n  ", pMCParam->logo_en);
	//get logo_hit_range
    pmxaTemp = mxGetField(pmxaMCParam, 0, sLogoHitRange);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->logo_hit_range[0]  = pui8Temp[0];
	pMCParam->logo_hit_range[1]  = pui8Temp[1];
	mexPrintf("logo_hit_range : %d, %d\n  ", pMCParam->logo_hit_range[0],
		                                     pMCParam->logo_hit_range[1]);
	//get logo_ext_range
    pmxaTemp = mxGetField(pmxaMCParam, 0, sLogoExtRange);
    pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->logo_ext_range[0]  = pui8Temp[0];
	pMCParam->logo_ext_range[1]  = pui8Temp[1];
	mexPrintf("logo_ext_range : %d, %d\n  ", pMCParam->logo_ext_range[0],
		                                     pMCParam->logo_ext_range[1]);
	//get logo_tuning_vec_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sLogoTuneVEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->logo_tuning_vec_en  = (pui8Temp[0]!=0);
	mexPrintf("logo_tuning_vec_en : %d\n  ", pMCParam->logo_tuning_vec_en);

	//get oob_en
	pmxaTemp = mxGetField(pmxaMCParam, 0, sOOBEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->oob_en  = (pui8Temp[0]!=0);
	mexPrintf("oob_en : %d\n  ", pMCParam->oob_en);
	//get oob_vec_range
    pmxaTemp = mxGetField(pmxaMCParam, 0, sOOBVecRange);
    pui16Temp = (UINT16*)  mxGetData(pmxaTemp);
	pMCParam->oob_vec_range[0]  = pui16Temp[0];
	pMCParam->oob_vec_range[1]  = pui16Temp[0];
	mexPrintf("oob_vec_range : %d, %d\n  ", pMCParam->oob_vec_range[0],
		                                    pMCParam->oob_vec_range[1]);

	//char                [32] = "out_sel"; 
	pmxaTemp = mxGetField(pmxaMCParam, 0, sOutSel);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->out_sel  = pui8Temp[0];
	mexPrintf("out_sel : %d\n  ", pMCParam->out_sel);

	//char         sGoodProtEn   [32] = "good_prot_en"; //bool       good_prot_en;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sGoodProtEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->good_prot_en  = (pui8Temp[0]!=0);
	mexPrintf("good_prot_en : %d\n  ", pMCParam->good_prot_en);

	//char         sBadProtEn    [32] = "bad_prot_en"; //bool       bad_prot_en;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sBadProtEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->bad_prot_en  = (pui8Temp[0]!=0);
	mexPrintf("bad_prot_en : %d\n  ", pMCParam->bad_prot_en);

    //char         sYOverlayMode [32] = "y_overlay_mode"; //UINT8      y_overlay_mode;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sYOverlayMode);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->y_overlay_mode  = pui8Temp[0];
	mexPrintf("y_overlay_mode : %d\n  ", pMCParam->y_overlay_mode);

    //char         sUVOverlayMode[32] = "uv_overlay_mode"; //UINT8      uv_overlay_mode;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sUVOverlayMode);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->uv_overlay_mode  = pui8Temp[0];
	mexPrintf("uv_overlay_mode : %d\n  ", pMCParam->uv_overlay_mode);

    //char         sOlKu         [32] = "ol_ku"; //INT8       ol_ku;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sOlKu);
	pi8Temp = (INT8*)  mxGetData(pmxaTemp);
	pMCParam->ol_ku  = pi8Temp[0];
	mexPrintf("ol_ku : %d\n  ", pMCParam->ol_ku);

	//char         sOlKv         [32] = "ol_kv"; //INT8       ol_kv;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sOlKv);
	pi8Temp = (INT8*)  mxGetData(pmxaTemp);
	pMCParam->ol_kv  = pi8Temp[0];
	mexPrintf("ol_kv : %d\n  ", pMCParam->ol_kv);

	//char         sGridEn       [32] = "grid_en"; //bool       grid_en;
	pmxaTemp = mxGetField(pmxaMCParam, 0, sGridEn);
	pui8Temp = (UINT8*)  mxGetData(pmxaTemp);
	pMCParam->grid_en  = (pui8Temp[0]!=0);
	mexPrintf("grid_en : %d\n  ", pMCParam->grid_en);


	return;
}

static UINT8 gAlphaH[8][8] =  {{4, 5, 6, 7, 7, 6, 5, 4},
                               {4, 4, 5, 5, 5, 5, 4, 4},
                               {2, 2, 4, 4, 4, 4, 2, 2},
                               {1, 1, 1, 2, 2, 1, 1, 1}, 
                               {1, 1, 1, 2, 2, 1, 1, 1},
                               {2, 2, 4, 4, 4, 4, 2, 2},
                               {4, 4, 5, 5, 5, 5, 4, 4},
                               {4, 5, 6, 7, 7, 6, 5, 4}};

static UINT8 gAlphaV[8][8] =  {{4, 4, 2, 1, 1, 2, 4, 4},
                               {5, 4, 2, 1, 1, 2, 5, 4},
                               {6, 5, 4, 1, 1, 4, 5, 6},
                               {7, 5, 4, 2, 2, 4, 5, 7}, 
                               {7, 5, 4, 2, 2, 4, 5, 7},
                               {6, 5, 4, 1, 1, 4, 5, 6},
                               {5, 4, 2, 1, 1, 2, 5, 4},
                               {4, 4, 2, 1, 1, 2, 4, 4}};

static UINT8 gAlphaD[8][8] =  {{4, 3, 2, 1, 1, 2, 3, 4},
                               {3, 3, 2, 1, 1, 2, 3, 3},
                               {2, 2, 1, 1, 1, 1, 2, 2},
                               {1, 1, 1, 1, 1, 1, 1, 1}, 
                               {1, 1, 1, 1, 1, 1, 1, 1},
                               {2, 2, 1, 1, 1, 1, 2, 2},
                               {3, 3, 2, 1, 1, 2, 3, 3},
                               {4, 3, 2, 1, 1, 2, 3, 4}};

INT16 vec_diff_abs(INT16* pVecA, INT16* pVecB)
{
	INT16 iDiff;
	iDiff = pVecA[0]>pVecB[0]?(pVecA[0]-pVecB[0]):(pVecB[0]-pVecA[0]);
	iDiff += pVecA[1]>pVecB[1]?(pVecA[1]-pVecB[1]):(pVecB[1]-pVecA[1]);
	return iDiff;
}

UINT8 adjust_alpha(INT16* pVecCt, INT16* pVecNb, UINT8 iAlpha,const T_MC_PARAM* pMCParam)
{
	INT16  iVecDiff;
	INT16  iFactor;
	if(!pMCParam->obmc_en)
		return 0;

	iVecDiff   = vec_diff_abs(pVecNb, pVecCt);

	if(iVecDiff <= pMCParam->obmc_vardiff_thr)
		return 0;
	else {
		iFactor = (iVecDiff - pMCParam->obmc_vardiff_thr)*pMCParam->obmc_vardiff_trans;
		if(iFactor > 256)
			iFactor = 256;
	}

	return (UINT8) (iAlpha * iFactor/16);
}

INT16 i16abs(INT16 iDat)
{
	iDat = iDat > 0 ? iDat : -iDat;
	return iDat;
}

int rand8()
{
    int result = (int)floor(rand()/(RAND_MAX + 1) * 8);
	return result;
}


void get_ext_logo_mask(const T_MC_PARAM* pMCParam, UINT8* pBlkLogo)
{
//	INT16  iFetPosPre[2], iFetPosCur[2];
//	INT16  iFetBlkPre[2], iFetBlkCur[2];
	INT16   iExtIdx[2], iBlkIdx[2], iBlkPos[2];
//	UINT16 iPicSize[2];
//	INT8   iResult;
	int    iTotalBlkNum;
//	bool   bHitPre, bHitCur, 
	bool   bBlkLogoExt;
	iTotalBlkNum = pMCParam->block_number[0]*pMCParam->block_number[1];

	//logo extension
	for(iBlkIdx[1] = 0; iBlkIdx[1] < pMCParam->block_number[1]; iBlkIdx[1]++)
		for(iBlkIdx[0] = 0; iBlkIdx[0] < pMCParam->block_number[0]; iBlkIdx[0]++)
		{
			bBlkLogoExt = false;

			for(iExtIdx[1]=-pMCParam->logo_ext_range[1]; iExtIdx[1]<= pMCParam->logo_ext_range[1]; iExtIdx[1]++)
			{
				for(iExtIdx[0]=-pMCParam->logo_ext_range[0]; iExtIdx[0]<= pMCParam->logo_ext_range[0]; iExtIdx[0]++)
				{
					iBlkPos[0] = iBlkIdx[0] + iExtIdx[0];
					iBlkPos[0] = iBlkPos[0]<0?0:iBlkPos[0]>(pMCParam->block_number[0]-1)?(pMCParam->block_number[0]-1):iBlkPos[0];
					iBlkPos[1] = iBlkIdx[1] + iExtIdx[1];
					iBlkPos[1] = iBlkPos[1]<0?0:iBlkPos[1]>(pMCParam->block_number[1]-1)?(pMCParam->block_number[1]-1):iBlkPos[1];
					if(pMCParam->logo_mask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]])
					{
						bBlkLogoExt = true;
						break;
					}

				}
				if(bBlkLogoExt)
					break;
			}
			pBlkLogo[iBlkIdx[0]+iBlkIdx[1]*pMCParam->block_number[0]] = bBlkLogoExt;
			
		}

}

//logo hit
INT8 logo_hit_test(const INT16* pVec, const UINT16* pPicPos, const UINT8* pBlkLogo, const T_MC_PARAM* pMCParam, const int* pOutSize)
{
	//0: no hit
	//1: hit pre
	//2: hit cur
	//3: hit both
	INT16  iFetPosPre[2], iFetPosCur[2];
	INT16  iFetBlkPre[2], iFetBlkCur[2];
	UINT16 iPicSize[2];
	INT8   iResult;
	int    iTotalBlkNum;
	bool   bHitPre, bHitCur;
	iTotalBlkNum = pMCParam->block_number[0]*pMCParam->block_number[1];
	//logo extension

	//pMCParam->logo_mask
	
	iPicSize[0] = pOutSize[0];//pMCParam->block_number[0]*pMCParam->block_size[0];
	iPicSize[1] = pOutSize[1];//pMCParam->block_number[1]*pMCParam->block_size[1];

	iFetPosPre[0] = pPicPos[0] - (INT16)(pVec[0]*1.0*pMCParam->temp_phase/128/pMCParam->vec_precision[0]);
	iFetPosPre[0] = iFetPosPre[0] < 0 ? 0: iFetPosPre[0] > (iPicSize[0] - 1) ? (iPicSize[0]-1): iFetPosPre[0];
	iFetBlkPre[0] = iFetPosPre[0]/pMCParam->block_size[0];

	iFetPosPre[1] = pPicPos[1] - (INT16)(pVec[1]*1.0*pMCParam->temp_phase/128/pMCParam->vec_precision[1]);
	iFetPosPre[1] = iFetPosPre[1] < 0 ? 0: iFetPosPre[1] > (iPicSize[1] - 1) ? (iPicSize[1]-1): iFetPosPre[1];
	iFetBlkPre[1] = iFetPosPre[1]/pMCParam->block_size[1];
	
	bHitPre = pBlkLogo[iFetBlkPre[0]+iFetBlkPre[1]*pMCParam->block_number[0]];

	iFetPosCur[0] = pPicPos[0] + (INT16)(pVec[0]*1.0*(128-pMCParam->temp_phase)/128/pMCParam->vec_precision[0]);
	iFetPosCur[0] = iFetPosCur[0] < 0 ? 0: (iFetPosCur[0] > (iPicSize[0] - 1)) ? (iPicSize[0]-1): iFetPosCur[0];
	iFetBlkCur[0] = iFetPosCur[0]/pMCParam->block_size[0];

	iFetPosCur[1] = pPicPos[1] + (INT16)(pVec[1]*1.0*(128-pMCParam->temp_phase)/128/pMCParam->vec_precision[1]);
	iFetPosCur[1] = iFetPosCur[1] < 0 ? 0: (iFetPosCur[1] > (iPicSize[1] - 1)) ? (iPicSize[1]-1): iFetPosCur[1];
	iFetBlkCur[1] = iFetPosCur[1]/pMCParam->block_size[1];
	
	bHitCur = pBlkLogo[iFetBlkCur[0]+iFetBlkCur[1]*pMCParam->block_number[0]];

	iResult = (bHitPre & bHitCur) ? 3 : bHitPre ? 1 : bHitCur ? 2 : 0;
	return iResult;

}


INT8 oob_test(const INT16* pVec, const UINT16* pPicPos, const T_MC_PARAM* pMCParam, const int* pOutSize)
{
	//0: no oob
	//1: cur oob
	//2: pre oob
	//3: all oob

	INT16  iFetPosPre[2], iFetPosCur[2];
	UINT16 iPicSize[2];
	UINT16 iLX, iRX, iTY, iBY;
	INT8   iResult;
	int    iTotalBlkNum;
	bool   bOOBPre, bOOBCur;
	iTotalBlkNum = pMCParam->block_number[0]*pMCParam->block_number[1];
	//logo extension

	//pMCParam->logo_mask

	
	iPicSize[0] = pOutSize[0];//pMCParam->block_number[0]*pMCParam->block_size[0];
	iPicSize[1] = pOutSize[1];//pMCParam->block_number[1]*pMCParam->block_size[1];
	if(pMCParam->oob_en)
	{
		iLX = (pMCParam->window[0] > 0) ?  pMCParam->window[0] : 0;
		iRX = (pMCParam->window[1] < (iPicSize[0]-1)) ? pMCParam->window[1] : iPicSize[0]-1;
		iTY = (pMCParam->window[2] > 0) ? pMCParam->window[2] : 0;
		iBY = (pMCParam->window[3] < (iPicSize[1]-1)) ? pMCParam->window[3] : iPicSize[1]-1;
	}
	else {
		iLX = 0;
		iRX = iPicSize[0]-1;
		iTY = 0;
		iBY = iPicSize[1]-1;
	}

	iFetPosPre[0] = pPicPos[0] - (INT16)(pVec[0]*1.0*pMCParam->temp_phase/128/pMCParam->vec_precision[0]);
	iFetPosPre[1] = pPicPos[1] - (INT16)(pVec[1]*1.0*pMCParam->temp_phase/128/pMCParam->vec_precision[1]);
	bOOBPre = ((iFetPosPre[0] < iLX) || (iFetPosPre[0]>iRX) ||(iFetPosPre[1] < iTY) || (iFetPosPre[1] > iBY));

	iFetPosCur[0] = pPicPos[0] + (INT16)(pVec[0]*1.0*(128-pMCParam->temp_phase)/128/pMCParam->vec_precision[0]);
	iFetPosCur[1] = pPicPos[1] + (INT16)(pVec[1]*1.0*(128-pMCParam->temp_phase)/128/pMCParam->vec_precision[1]);
	bOOBCur = ((iFetPosCur[0] < iLX) || (iFetPosCur[0]>iRX) ||(iFetPosCur[1] < iTY) || (iFetPosCur[1] > iBY));

	iResult = (bOOBPre & bOOBCur) ? 3 : bOOBPre ? 1 : bOOBCur ? 2 : 0;
	return iResult;

}

void get_ext_dehalo_mask(const T_MC_PARAM* pMCParam, INT8* pExtBlkCUCMask, UINT8* pExtBlkBadMask)
{
	INT16  iBlkIdx[2], iBlkNum[2], iNbIdx[2], iNbBlkPos[2];
	INT8*  pCUCMask = pMCParam->cuc_mask;
	UINT8  iCovCnt, iUncovCnt, iBadCnt;
	INT8   iCUCValue;
	iBlkNum[0] = pMCParam->block_number[0];
	iBlkNum[1] = pMCParam->block_number[1];
	for(iBlkIdx[1]=0; iBlkIdx[1]<iBlkNum[1]; iBlkIdx[1]++)
		for(iBlkIdx[0]=0; iBlkIdx[0]<iBlkNum[0]; iBlkIdx[0]++)
		{
			iCovCnt = 0; iUncovCnt = 0; iBadCnt = 0;
			for(iNbIdx[0]=-1; iNbIdx[0]<=1; iNbIdx[0]++)
				for(iNbIdx[1]=-1; iNbIdx[1]<=1; iNbIdx[1]++)
				{
					iNbBlkPos[0] = iBlkIdx[0] + iNbIdx[0];
					iNbBlkPos[0] = iNbBlkPos[0]<0 ? 0 : iNbBlkPos[0]>iBlkNum[0]-1 ? iBlkNum[0]-1 : iNbBlkPos[0];
					iNbBlkPos[1] = iBlkIdx[1] + iNbIdx[1];
					iNbBlkPos[1] = iNbBlkPos[1]<0 ? 0 : iNbBlkPos[1]>iBlkNum[1]-1 ? iBlkNum[1]-1 : iNbBlkPos[1];
					iCUCValue = pCUCMask[iNbBlkPos[0]+iNbBlkPos[1]*iBlkNum[0]];
					// -1: cover; 1 uncover; 7 CUC conflict; 5: bad vector; 3:good vector 
					if     ((iCUCValue == -1) || (iCUCValue == 7))
						iCovCnt ++;
					if((iCUCValue == 1) || (iCUCValue == 7))
						iUncovCnt ++;

					if((iCUCValue == 7) || (iCUCValue == 5))
						iBadCnt ++;
				}
			if((iCovCnt> pMCParam->cuc_hi_cnt_thr)&&(iUncovCnt< pMCParam->cuc_low_cnt_thr))
				pExtBlkCUCMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = -1;
			else if((iUncovCnt> pMCParam->cuc_hi_cnt_thr)&&(iCovCnt< pMCParam->cuc_low_cnt_thr))
				pExtBlkCUCMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 1;
			else
				pExtBlkCUCMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 0;

			if(iBadCnt > pMCParam->cuc_hi_cnt_thr)
				pExtBlkBadMask[iBlkIdx[0]+iBlkIdx[1]*iBlkNum[0]] = 1;

		}
}

void get_masks(const T_MC_PARAM* pMCParam, UINT8* pOBMCAlpha, INT16* pOBMCVec, UINT8*  pRefineMask, 
					INT8* pLogohitMask, UINT8* pLogoAlpha, INT8* pOOBMask, INT8* pDehaloAlpha, UINT8* pBadAlpha, const int* pOutSize)
{
	UINT16 iPicSize[2];
	UINT16 iBlkIdx[2], iPInBIdx[2], iPicPos[2];
	INT16  iBlkPos[2];
	UINT8  iAlphaCt, iAlphaH, iAlphaV, iAlphaD;
	INT16  iVecCt[2], iVecV[2], iVecH[2], iVecD[2];
	INT16  iSumDiff;
	UINT8  iRefine;
	bool   bDirX, bDirY, bDir45, bDir135;
	INT16  iAbsVx, iAbsVy, iXYDiff, iXYSize;
	UINT8  iLogoAlphaCt, iLogoAlphaH, iLogoAlphaV, iLogoAlphaD;
	UINT8  iLogoCt, iLogoH, iLogoV, iLogoD;
	UINT8  iLogoAlpha;
	int    iTotalBlkNum;
	INT8*  pCUCMask = pMCParam->cuc_mask;

	INT8   iCUCCt, iCUCH, iCUCV, iCUCD;
	UINT8  iDehaloAlphaCt, iDehaloAlphaH, iDehaloAlphaV, iDehaloAlphaD;
	INT8   iDehaloAlpha;
	UINT8  iBadCt, iBadH, iBadV, iBadD;
	UINT8  iBadAlpha;


	INT8   iRfCand[16] = { -1, -1, -1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1}; 
	int    iRfIdx;
	const INT16* pBlkVec = pMCParam->vector;
	const UINT8* pBlkLogo= pMCParam->logo_mask;
	UINT8* pExtBlkLogo;
	INT8*  pExtBlkCUCMask;
	UINT8* pExtBlkBadMask;
	bool   bYOOP, bXOOP;
	float  fBkRatio[2];
	int    iAlphaIdx[2], iHalfBlk[2];

	iTotalBlkNum = pMCParam->block_number[0]*pMCParam->block_number[1];
	pExtBlkLogo    = (UINT8*)malloc(iTotalBlkNum*sizeof(UINT8));
	pExtBlkCUCMask = (INT8*) malloc(iTotalBlkNum*sizeof(INT8));
	pExtBlkBadMask = (UINT8*)malloc(iTotalBlkNum*sizeof(UINT8));

	iPicSize[0] = pOutSize[0];//pMCParam->block_number[0]*pMCParam->block_size[0];
	iPicSize[1] = pOutSize[1];//pMCParam->block_number[1]*pMCParam->block_size[1];

	get_ext_logo_mask(pMCParam,pExtBlkLogo);
	get_ext_dehalo_mask(pMCParam, pExtBlkCUCMask, pExtBlkBadMask);

	fBkRatio[0] = (float)8.0/pMCParam->block_size[0];
	fBkRatio[1] = (float)8.0/pMCParam->block_size[1];
	iHalfBlk[0] = pMCParam->block_size[0]/2;
	iHalfBlk[1] = pMCParam->block_size[1]/2;


	for(iBlkIdx[1]=0; iBlkIdx[1]<pMCParam->block_number[1]; iBlkIdx[1]++)
		for(iBlkIdx[0]=0; iBlkIdx[0]<pMCParam->block_number[0]; iBlkIdx[0]++)
			for(iPInBIdx[1]=0; iPInBIdx[1]<pMCParam->block_size[1]; iPInBIdx[1]++)
			{
				bYOOP = ((iBlkIdx[1] * pMCParam->block_size[1] + iPInBIdx[1])>(pOutSize[1]-1));
				if(bYOOP)
					break;
 				for(iPInBIdx[0]=0; iPInBIdx[0]<pMCParam->block_size[0]; iPInBIdx[0]++)
				{
					iAlphaIdx[0] = (int)(iPInBIdx[0] * fBkRatio[0]);iAlphaIdx[1] = (int)(iPInBIdx[1] * fBkRatio[1]);
					bXOOP = ((iBlkIdx[0] * pMCParam->block_size[0] + iPInBIdx[0])>(pOutSize[0]-1));
					if(bXOOP)
						break;
					iPicPos[0] = iBlkIdx[0] * pMCParam->block_size[0] + iPInBIdx[0];
					iPicPos[1] = iBlkIdx[1] * pMCParam->block_size[1] + iPInBIdx[1];
					//cent
					iBlkPos[0] = iBlkIdx[0];
					iBlkPos[1] = iBlkIdx[1];
					iVecCt[0]  = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iVecCt[1]  = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0] + pMCParam->block_number[0]*pMCParam->block_number[1]];
					iLogoCt    = pExtBlkLogo[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iCUCCt     = pExtBlkCUCMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iBadCt     = pExtBlkBadMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					//left/right
					iBlkPos[0] = iPInBIdx[0] <= iHalfBlk[0] ? iBlkIdx[0]-1 : iBlkIdx[0]+1; 
					iBlkPos[0] = (iBlkPos[0]<0? 0: iBlkPos[0]> (pMCParam->block_number[0]-1)?(pMCParam->block_number[0]-1) : iBlkPos[0]);
					iBlkPos[1] = iBlkIdx[1];
					iVecH[0]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iVecH[1]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0] + pMCParam->block_number[0]*pMCParam->block_number[1]];
					iAlphaH    = gAlphaH[iAlphaIdx[0]][iAlphaIdx[1]];
                    iAlphaH    = adjust_alpha(iVecCt, iVecH, iAlphaH, pMCParam);
					iLogoH     = pExtBlkLogo[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iLogoAlphaH= gAlphaH[iAlphaIdx[0]][iAlphaIdx[1]];
					iCUCH      = pExtBlkCUCMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iDehaloAlphaH = gAlphaH[iAlphaIdx[0]][iAlphaIdx[1]];
					iBadH      = pExtBlkBadMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					//up/dn
					iBlkPos[0] = iBlkIdx[0];
					iBlkPos[1] = iPInBIdx[1] <= iHalfBlk[1] ? iBlkIdx[1]-1 : iBlkIdx[1]+1; 
					iBlkPos[1] = (iBlkPos[1]<0? 0: iBlkPos[1]> (pMCParam->block_number[1]-1)?(pMCParam->block_number[1]-1) : iBlkPos[1]);
					iVecV[0]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iVecV[1]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0] + pMCParam->block_number[0]*pMCParam->block_number[1]];
					iAlphaV    = gAlphaV[iAlphaIdx[0]][iAlphaIdx[1]];
                    iAlphaV    = adjust_alpha(iVecCt, iVecV, iAlphaV, pMCParam);
					iLogoV     = pExtBlkLogo[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iLogoAlphaV= gAlphaV[iAlphaIdx[0]][iAlphaIdx[1]];
					iCUCV      = pExtBlkCUCMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iDehaloAlphaV = gAlphaV[iAlphaIdx[0]][iAlphaIdx[1]];
					iBadV      = pExtBlkBadMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					//diag
					iBlkPos[0] = iPInBIdx[0] <= iHalfBlk[0] ? iBlkIdx[0]-1 : iBlkIdx[0]+1; 
					iBlkPos[0] = (iBlkPos[0]<0? 0: iBlkPos[0]> (pMCParam->block_number[0]-1)?(pMCParam->block_number[0]-1) : iBlkPos[0]);
					iBlkPos[1] = iPInBIdx[1] <= iHalfBlk[1] ? iBlkIdx[1]-1 : iBlkIdx[1]+1; 
					iBlkPos[1] = (iBlkPos[1]<0? 0: iBlkPos[1]> (pMCParam->block_number[1]-1)?(pMCParam->block_number[1]-1) : iBlkPos[1]);
					iVecD[0]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iVecD[1]   = pBlkVec[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0] + pMCParam->block_number[0]*pMCParam->block_number[1]];
					iAlphaD    = gAlphaD[iAlphaIdx[0]][iAlphaIdx[1]];
                    iAlphaD    = adjust_alpha(iVecCt, iVecD, iAlphaD, pMCParam);
					iLogoD     = pExtBlkLogo[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iLogoAlphaD= gAlphaD[iAlphaIdx[0]][iAlphaIdx[1]];
					iCUCD      = pExtBlkCUCMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];
					iDehaloAlphaD = gAlphaD[iAlphaIdx[0]][iAlphaIdx[1]];
					iBadD      = pExtBlkBadMask[iBlkPos[0]+iBlkPos[1]*pMCParam->block_number[0]];

					//
					iAlphaCt		= 255 - iAlphaH - iAlphaV - iAlphaD;
					iLogoAlphaCt	= 16-iLogoAlphaH-iLogoAlphaV-iLogoAlphaD;
					iLogoAlpha		= iLogoAlphaH * iLogoH + iLogoAlphaV * iLogoV + iLogoAlphaD * iLogoD + iLogoAlphaCt * iLogoCt; 

					//
					iDehaloAlphaCt = 16 - iDehaloAlphaH - iDehaloAlphaV - iDehaloAlphaD;
					iDehaloAlpha   = iDehaloAlphaH * iCUCH + iDehaloAlphaV * iCUCV + iDehaloAlphaD * iCUCD + iDehaloAlphaCt * iCUCCt;
					iDehaloAlpha   = pMCParam->cuc_alpha_en? iDehaloAlpha : (iDehaloAlpha > 2) ? 16 : (iDehaloAlpha < -2) ? -16 : 0;


					//
					iBadAlpha =  iLogoAlphaH * iBadH + iLogoAlphaV * iBadV + iLogoAlphaD * iBadD + iLogoAlphaCt * iBadCt;
					//refine mask
					iSumDiff   = vec_diff_abs(iVecCt, iVecV) + vec_diff_abs(iVecCt, iVecH) + vec_diff_abs(iVecCt, iVecD);
					if((iSumDiff < pMCParam->refine_vardiff_thr)&&pMCParam->refine_en)
					{
						iRefine = 1;
						if(!pMCParam->refine_cent_only)
						{
							iVecCt[0] = (iVecCt[0] + iVecH[0] + iVecV[0] + iVecD[0])/4;
							iVecCt[1] = (iVecCt[1] + iVecH[1] + iVecV[1] + iVecD[1])/4;
						}
						if(pMCParam->refine_dir_en)
						{
							
							iAbsVx  = i16abs(iVecCt[0]);
							iAbsVy  = i16abs(iVecCt[1]);
							iXYDiff = (iAbsVx>iAbsVy) ? (iAbsVy-iAbsVx):(iAbsVx-iAbsVy);
							iXYSize = iAbsVx + iAbsVy;
							bDirX  = (iAbsVx > iAbsVy) && (iXYSize > pMCParam->refine_dir_minvec_th) && (iXYDiff >= pMCParam->refine_dir_mindiff_th);
							bDirY  = (iAbsVx < iAbsVy) && (iXYSize > pMCParam->refine_dir_minvec_th) && (iXYDiff >= pMCParam->refine_dir_mindiff_th); 
							bDir45 = (iVecCt[0]>0 && iVecCt[1]>0||iVecCt[0]<0 && iVecCt[1]<0) && (iXYSize > pMCParam->refine_dir_minvec_th) && (iXYDiff <= pMCParam->refine_dir_maxdiff_th);
							bDir135= (iVecCt[0]>0 && iVecCt[1]<0||iVecCt[0]<0 && iVecCt[1]>0) && (iXYSize > pMCParam->refine_dir_minvec_th) && (iXYDiff <= pMCParam->refine_dir_maxdiff_th);
							if(bDirX)
							{
								iVecH[0] = iVecCt[0] + pMCParam->refine_length;
								iVecH[1] = iVecCt[1];
								iVecV[0] = iVecCt[0] - pMCParam->refine_length;
								iVecV[1] = iVecCt[1];
							}
							else if(bDirY)
							{
								iVecH[1] = iVecCt[1] + pMCParam->refine_length;
								iVecH[0] = iVecCt[0];
								iVecV[1] = iVecCt[1] - pMCParam->refine_length;
								iVecV[0] = iVecCt[0];
							}
							else if(bDir45)
							{
								iVecH[0] = iVecCt[0] + pMCParam->refine_length;
								iVecH[1] = iVecCt[1] + pMCParam->refine_length;
								iVecV[0] = iVecCt[0] - pMCParam->refine_length;
								iVecV[1] = iVecCt[1] - pMCParam->refine_length;
							}
							else if(bDir135)
							{
								iVecH[0] = iVecCt[0] + pMCParam->refine_length;
								iVecH[1] = iVecCt[1] - pMCParam->refine_length;
								iVecV[0] = iVecCt[0] - pMCParam->refine_length;
								iVecV[1] = iVecCt[1] + pMCParam->refine_length;
							}
							else
							{
								iRfIdx = rand8();
								iVecH[0] = iVecCt[0] + iRfCand[2*iRfIdx+0] * pMCParam->refine_length;
								iVecH[1] = iVecCt[1] + iRfCand[2*iRfIdx+1] * pMCParam->refine_length;
								iRfIdx = rand8();
								iVecV[0] = iVecCt[0] + iRfCand[2*iRfIdx+0] * pMCParam->refine_length;
								iVecV[1] = iVecCt[1] + iRfCand[2*iRfIdx+1] * pMCParam->refine_length;
							}

							iRfIdx = rand8();
							iVecD[0] = iVecCt[0] + iRfCand[2*iRfIdx+0] * pMCParam->refine_length;
							iVecD[1] = iVecCt[1] + iRfCand[2*iRfIdx+1] * pMCParam->refine_length;

						}
					}
					else
						iRefine = 0;

					//logo hit
					pLogohitMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0] = logo_hit_test(iVecCt, iPicPos, pExtBlkLogo, pMCParam, pOutSize);
					pLogohitMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1] = logo_hit_test(iVecH,  iPicPos, pExtBlkLogo, pMCParam, pOutSize);
					pLogohitMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2] = logo_hit_test(iVecD,  iPicPos, pExtBlkLogo, pMCParam, pOutSize);
					pLogohitMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3] = logo_hit_test(iVecV,  iPicPos, pExtBlkLogo, pMCParam, pOutSize);


					pLogoAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]] = iLogoAlpha; // 0 to 16
					//Dehalo 
					pDehaloAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]] = iDehaloAlpha;
					//pDehaloMask[iPicPos[0]+iPicPos[1]*iPicSize[0]]  = iDehaloAlpha > 0? 1 : -1;
					//bad
					pBadAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]] = iBadAlpha;
					//oob
					pOOBMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0] = oob_test(iVecCt, iPicPos, pMCParam, pOutSize);
					pOOBMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1] = oob_test(iVecH,  iPicPos, pMCParam, pOutSize);
					pOOBMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2] = oob_test(iVecD,  iPicPos, pMCParam, pOutSize);
					pOOBMask[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3] = oob_test(iVecV,  iPicPos, pMCParam, pOutSize);

					pOBMCAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0] = iAlphaCt;
					pOBMCAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1] = iAlphaH;
					pOBMCAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2] = iAlphaD;
					pOBMCAlpha[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3] = iAlphaV;

					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0] = iVecCt[0];
					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1] = iVecCt[1];

					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2] = iVecH[0];
					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3] = iVecH[1];

					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*4] = iVecD[0];
					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*5] = iVecD[1];

					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*6] = iVecV[0];
					pOBMCVec[iPicPos[0]+iPicPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*7] = iVecV[1];

                    pRefineMask[iPicPos[0]+iPicPos[1]*iPicSize[0]] = iRefine;

				}
			}
	free(pExtBlkLogo);

}



void get_pixel(const T_MC_PARAM* pMCParam,const UINT8* pYUV, const UINT16* pSize,  int iPolarity, INT32* iPos, INT16* iOut, const int* pOutSize)
{
	INT32 iPosI[2], iPosF[2];
	INT16 iPrecision[2];
	INT16 iPicSize[2];
	INT16 iLX, iRX, iTY, iBY;
	UINT8 iYUVtl[3], iYUVtr[3], iYUVbl[3], iYUVbr[3];
	UINT8 iChIdx;

	iPicSize[0] = pOutSize[0];//pMCParam->block_number[0] * pMCParam->block_size[0];
	iPicSize[1] = pOutSize[1];//pMCParam->block_number[1] * pMCParam->block_size[1];

	iPrecision[0] = pMCParam->vec_precision[0]*128;
	iPrecision[1] = pMCParam->vec_precision[1]*128;

	iPosI[0] = (INT16)floor(iPos[0]*1.0/iPrecision[0]);
	iPosI[1] = (INT16)floor(iPos[1]*1.0/iPrecision[1]);

	iPosF[0] = iPos[0] - iPosI[0]*iPrecision[0];
	iPosF[1] = iPos[1] - iPosI[1]*iPrecision[1];

	iLX = iPosI[0]  ; iLX = (iLX < 0) ? 0 : (iLX > (iPicSize[0]-1)) ? (iPicSize[0]-1) : iLX;
	iRX = iPosI[0]+1; iRX = (iRX < 0) ? 0 : (iRX > (iPicSize[0]-1)) ? (iPicSize[0]-1) : iRX;

	iTY = iPosI[1]  ; iTY = (iTY < 0) ? 0 : (iTY > (iPicSize[1]-1)) ? (iPicSize[1]-1) : iTY;
	iBY = iPosI[1]+1; iBY = (iBY < 0) ? 0 : (iBY > (iPicSize[1]-1)) ? (iPicSize[1]-1) : iBY;

	for( iChIdx = 0; iChIdx < 3; iChIdx++)
	{
		iYUVtl[iChIdx] = pYUV[iLX + iTY * iPicSize[0] + iPicSize[0]*iPicSize[1]*iChIdx];
		iYUVtr[iChIdx] = pYUV[iRX + iTY * iPicSize[0] + iPicSize[0]*iPicSize[1]*iChIdx];
		iYUVbl[iChIdx] = pYUV[iLX + iBY * iPicSize[0] + iPicSize[0]*iPicSize[1]*iChIdx];
		iYUVbr[iChIdx] = pYUV[iRX + iBY * iPicSize[0] + iPicSize[0]*iPicSize[1]*iChIdx];
		iOut[iChIdx] = (iYUVtl[iChIdx] * (iPrecision[0]-iPosF[0]) * (iPrecision[1]-iPosF[1]) +
			            iYUVtr[iChIdx] *                iPosF[0]  * (iPrecision[1]-iPosF[1]) +
			            iYUVbl[iChIdx] * (iPrecision[0]-iPosF[0]) *                iPosF[1]  +
			            iYUVbr[iChIdx] *                iPosF[0]  *                iPosF[1])/(iPrecision[0]*iPrecision[1]);

	}

    return;
}

INT16 i16med3(INT16 iPC, INT16 iP, INT16 iC, UINT8* pIdx)
{
	if((iPC >= iP) && (iPC <= iC) ||
	   (iPC <= iP) && (iPC >= iC))
	{ 
		*pIdx=0;
		return iPC;
	}
	else if((iP >= iPC) && (iP <= iC) ||
		    (iP <= iPC) && (iP >= iC))
	{
		*pIdx = 1;
		return iP;
	}
	else
	{
		*pIdx = 2;
		return iC;
	}
}


void get_picture(const UINT8* pPreYUV, const UINT16* pPreSize, int iPrePolarity,
		          const UINT8* pCurYUV, const UINT16* pCurSize, int iCurPolarity,
				  const T_MC_PARAM* pMCParam,
				  const UINT8* pOBMCAlpha, const INT16* pOBMCVec, const UINT8* pRefineMask, const INT8* pLogohitMask, const UINT8* pLogoAlpha,
				  const INT8* pOOBMask, 
				  const INT8* pDehaloAlpha, const UINT8* pBadAlpha,
				  UINT8* pYUV, const int* pOutSize)
{

	INT16    iPicSize[2];
	INT16    iPicIdx[2];
	INT16    iP0[3], iPv[3], iPh[3], iPd[3], iPct[3], iP[3];
	INT16    iC0[3], iCv[3], iCh[3], iCd[3], iCct[3], iC[3];
	INT16    iPC0[3], iOBMCP[3], iOBMCC[3], iPC[3];
	INT16    iPrf[3], iCrf[3];
	INT32    iPos[2];
	INT16    iVec[2];
	INT16    iVecCt[2];

	UINT8    iRefine;
	INT8     iLogohitMaskV, iLogohitMaskH, iLogohitMaskD, iLogohitMaskCt;
	UINT8    iOBMCAlphaV, iOBMCAlphaH, iOBMCAlphaD, iOBMCAlphaCt;
	INT8     iOOBV, iOOBH, iOOBD, iOOBCt;
	INT16    iDiffCt, iDiffH, iDiffV, iDiffD;

	INT8     iDehaloAlpha;
	UINT8    iLogoAlpha, iBadAlpha;
	UINT8    iChIdx;

	UINT8  iIdx;
	INT16  iM3v[3];
	INT16  iM3v0[3];
	UINT8  iMCOut[3];
//	INT32  iOLSrc[3];
//	UINT8  iOLOut[3];
	INT16  iMux[3], iBBad[3], iBLogo[3];
	INT16  iPicOut[3];
    INT16  iYol, iUol, iVol;


	iPicSize[0]  = pOutSize[0];//pMCParam->block_number[0]*pMCParam->block_size[0];
	iPicSize[1]  = pOutSize[1];//pMCParam->block_number[1]*pMCParam->block_size[1];
	for(iPicIdx[1] = 0; iPicIdx[1]<iPicSize[1]; iPicIdx[1]++)
		for(iPicIdx[0] = 0; iPicIdx[0]<iPicSize[0]; iPicIdx[0]++)
		{
			//v0 
			iVec[0] = 0;
			iVec[1] = 0;
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128-iVec[0]*pMCParam->temp_phase;
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128-iVec[1]*pMCParam->temp_phase;
			get_pixel(pMCParam, pPreYUV, pPreSize, iPrePolarity, iPos, iP0, pOutSize);
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128+iVec[0]*(128-pMCParam->temp_phase);
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128+iVec[1]*(128-pMCParam->temp_phase);
			get_pixel(pMCParam, pCurYUV, pCurSize, iCurPolarity, iPos, iC0, pOutSize);

			//Ct
			iVec[0] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0];
			iVec[1] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1];
			iVecCt[0] = iVec[0]; iVecCt[1] = iVec[1];
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128-iVec[0]*pMCParam->temp_phase;
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128-iVec[1]*pMCParam->temp_phase;
			get_pixel(pMCParam, pPreYUV, pPreSize, iPrePolarity, iPos, iPct, pOutSize);
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128+iVec[0]*(128-pMCParam->temp_phase);
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128+iVec[1]*(128-pMCParam->temp_phase);
			get_pixel(pMCParam, pCurYUV, pCurSize, iCurPolarity, iPos, iCct, pOutSize);
			iPos[0] = iPicIdx[0]; iPos[1] = iPicIdx[1];
			iLogohitMaskCt = pLogohitMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0];
			iOOBCt  = pOOBMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0];
			iOBMCAlphaCt = pOBMCAlpha[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*0];
			//H
			iVec[0] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2];
			iVec[1] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3];
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128-iVec[0]*pMCParam->temp_phase;
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128-iVec[1]*pMCParam->temp_phase;
			get_pixel(pMCParam, pPreYUV, pPreSize, iPrePolarity, iPos, iPh, pOutSize);
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128+iVec[0]*(128-pMCParam->temp_phase);
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128+iVec[1]*(128-pMCParam->temp_phase);
			get_pixel(pMCParam, pCurYUV, pCurSize, iCurPolarity, iPos,iCh, pOutSize);
			iPos[0] = iPicIdx[0]; iPos[1] = iPicIdx[1];
			iLogohitMaskH = pLogohitMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1];
            iOOBH   = pOOBMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1];
			iOBMCAlphaH  = pOBMCAlpha[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*1];
			//V
			iVec[0] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*6];
			iVec[1] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*7];
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128-iVec[0]*pMCParam->temp_phase;
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128-iVec[1]*pMCParam->temp_phase;
			get_pixel(pMCParam, pPreYUV, pPreSize, iPrePolarity, iPos, iPv, pOutSize);
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128+iVec[0]*(128-pMCParam->temp_phase);
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128+iVec[1]*(128-pMCParam->temp_phase);
			get_pixel(pMCParam, pCurYUV, pCurSize, iCurPolarity, iPos, iCv, pOutSize);
			iPos[0] = iPicIdx[0]; iPos[1] = iPicIdx[1];
			iLogohitMaskV = pLogohitMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3];
            iOOBV   = pOOBMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3];
			iOBMCAlphaV  = pOBMCAlpha[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*3];
			//D
			iVec[0] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*4];
			iVec[1] = pOBMCVec[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*5];
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128-iVec[0]*pMCParam->temp_phase;
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128-iVec[1]*pMCParam->temp_phase;
			get_pixel(pMCParam, pPreYUV, pPreSize, iPrePolarity, iPos, iPd, pOutSize);
			iPos[0] = iPicIdx[0]*pMCParam->vec_precision[0]*128+iVec[0]*(128-pMCParam->temp_phase);
			iPos[1] = iPicIdx[1]*pMCParam->vec_precision[1]*128+iVec[1]*(128-pMCParam->temp_phase);
			get_pixel(pMCParam, pCurYUV, pCurSize, iCurPolarity, iPos,iCd, pOutSize);
			iPos[0] = iPicIdx[0]; iPos[1] = iPicIdx[1];
			iLogohitMaskD = pLogohitMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2]; 
            iOOBD   = pOOBMask[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2];
			iOBMCAlphaD  = pOBMCAlpha[iPos[0]+iPos[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*2];


			iPos[0] = iPicIdx[0]; iPos[1] = iPicIdx[1];
			//logo
			iLogoAlpha   = pLogoAlpha[iPos[0]+iPos[1]*iPicSize[0]]; // 0 to 16
			//Dehalo 
			iDehaloAlpha = pDehaloAlpha[iPos[0]+iPos[1]*iPicSize[0]];//-16 to 16
			//bad
			iBadAlpha    = pBadAlpha[iPos[0]+iPos[1]*iPicSize[0]];
			//refine
			iRefine      = pMCParam->refine_en ? pRefineMask[iPos[0]+iPos[1]*iPicSize[0]] : 0;

			//refine select

			iDiffCt = ((iPct[0] > iCct[0]) ? (iPct[0] - iCct[0]) : (iCct[0] - iPct[0])) +
				      ((iPct[1] > iCct[1]) ? (iPct[1] - iCct[1]) : (iCct[1] - iPct[1])) +
					  ((iPct[2] > iCct[2]) ? (iPct[2] - iCct[2]) : (iCct[2] - iPct[2]));

			iDiffH  = ((iPh[0] > iCh[0]) ? (iPh[0] - iCh[0]) : (iCh[0] - iPh[0])) +
				      ((iPh[1] > iCh[1]) ? (iPh[1] - iCh[1]) : (iCh[1] - iPh[1])) +
					  ((iPh[2] > iCh[2]) ? (iPh[2] - iCh[2]) : (iCh[2] - iPh[2]));

			iDiffV  = ((iPv[0] > iCv[0]) ? (iPv[0] - iCv[0]) : (iCv[0] - iPv[0])) +
				      ((iPv[1] > iCv[1]) ? (iPv[1] - iCv[1]) : (iCv[1] - iPv[1])) +
					  ((iPv[2] > iCv[2]) ? (iPv[2] - iCv[2]) : (iCv[2] - iPv[2]));

			iDiffD  = ((iPd[0] > iCd[0]) ? (iPd[0] - iCd[0]) : (iCd[0] - iPd[0])) +
				      ((iPd[1] > iCd[1]) ? (iPd[1] - iCd[1]) : (iCd[1] - iPd[1])) +
					  ((iPd[2] > iCd[2]) ? (iPd[2] - iCd[2]) : (iCd[2] - iPd[2]));

			if((iDiffCt <= iDiffH) && (iDiffCt <= iDiffV) && (iDiffCt <= iDiffD))
			{
				iPrf[0] = iPct[0];iPrf[1] = iPct[1];iPrf[2] = iPct[2];
				iCrf[0] = iCct[0];iCrf[1] = iCct[1];iCrf[2] = iCct[2];
			}
			else if((iDiffH <= iDiffCt) && (iDiffH <= iDiffV) && (iDiffH <= iDiffD))
			{
				iPrf[0] = iPh[0];iPrf[1] = iPh[1];iPrf[2] = iPh[2];
				iCrf[0] = iCh[0];iCrf[1] = iCh[1];iCrf[2] = iCh[2];
			}
			else if((iDiffV <= iDiffCt) && (iDiffV <= iDiffH) && (iDiffV <= iDiffD))
			{
				iPrf[0] = iPv[0];iPrf[1] = iPv[1];iPrf[2] = iPv[2];
				iCrf[0] = iCv[0];iCrf[1] = iCv[1];iCrf[2] = iCv[2];
			}
			else
			{
				iPrf[0] = iPd[0];iPrf[1] = iPd[1];iPrf[2] = iPd[2];
				iCrf[0] = iCd[0];iCrf[1] = iCd[1];iCrf[2] = iCd[2];
			}

			//////////////////////////////////////
			//replacement
			//oob	//0: no oob
					//1: pre oob
					//2: cur oob
					//3: all oob
					//0: no hit
			//logohit
			//1: hit pre
			//2: hit cur
			//3: hit both
			
			if((iOOBCt == 2)&&pMCParam->oob_en||(iLogohitMaskCt == 2)&&pMCParam->logo_en)
			{
				iCct[0]= iPct[0];iCct[1]= iPct[1];iCct[2]= iPct[2]; 
			}
			else if((iOOBCt == 1)&&pMCParam->oob_en||(iLogohitMaskCt == 1)&&pMCParam->logo_en)
			{
				iPct[0]= iCct[0];iPct[1]= iCct[1];iPct[2]= iCct[2]; 
			}
			else if((iOOBCt == 3)&&pMCParam->oob_en||(iLogohitMaskCt == 3)&&pMCParam->logo_en)
			{
				iPct[0]= iP0[0];iPct[1]= iP0[1];iPct[2]= iP0[2];
				iCct[0]= iC0[0];iCct[1]= iC0[1];iCct[2]= iC0[2];
			}

			if((iOOBH == 2)&&pMCParam->oob_en||(iLogohitMaskH == 2)&&pMCParam->logo_en)
			{
				iCh[0]= iPh[0];iCh[1]= iPh[1];iCh[2]= iPh[2];
			}
			else if((iOOBH == 1)&&pMCParam->oob_en||(iLogohitMaskH == 1)&&pMCParam->logo_en)
			{	iPh[0]= iCh[0];iPh[1]= iCh[1];iPh[2]= iCh[2];} 
			else if((iOOBH == 3)&&pMCParam->oob_en||(iLogohitMaskH == 3)&&pMCParam->logo_en)
			{
				iPh[0]= iP0[0];iPh[1]= iP0[1];iPh[2]= iP0[2];
				iCh[0]= iC0[0];iCh[1]= iC0[1];iCh[2]= iC0[2];
			}

			if((iOOBV == 2)&&pMCParam->oob_en||(iLogohitMaskV == 2)&&pMCParam->logo_en)
			{	iCv[0]= iPv[0];iCv[1]= iPv[1];iCv[2]= iPv[2]; }
			else if((iOOBV == 1)&&pMCParam->oob_en||(iLogohitMaskV == 1)&&pMCParam->logo_en)
			{	iPv[0]= iCv[0];iPv[1]= iCv[1];iPv[2]= iCv[2]; }
			else if((iOOBV == 3)&&pMCParam->oob_en||(iLogohitMaskV == 3)&&pMCParam->logo_en)
			{
				iPv[0]= iP0[0];iPv[1]= iP0[1];iPv[2]= iP0[2];
				iCv[0]= iC0[0];iCv[1]= iC0[1];iCv[2]= iC0[2];
			}

			if((iOOBD == 2)&&pMCParam->oob_en||(iLogohitMaskD == 2)&&pMCParam->logo_en)
			{	iCd[0]= iPd[0];iCd[1]= iPd[1];iCd[2]= iPd[2]; }
			else if((iOOBD == 1)&&pMCParam->oob_en||(iLogohitMaskD == 1)&&pMCParam->logo_en)
			{	iPd[0]= iCd[0];iPd[1]= iCd[1];iPd[2]= iCd[2]; }
			else if((iOOBD == 3)&&pMCParam->oob_en||(iLogohitMaskD == 3)&&pMCParam->logo_en)
			{
				iPd[0]= iP0[0];iPd[1]= iP0[1];iPd[2]= iP0[2];
				iCd[0]= iC0[0];iCd[1]= iC0[1];iCd[2]= iC0[2];
			}




			iOBMCP[0] = (iOBMCAlphaH * iPh[0] + iOBMCAlphaV * iPv[0] + iOBMCAlphaD * iPd[0] + iOBMCAlphaCt * iPct[0])/255;
			iOBMCC[0] = (iOBMCAlphaH * iCh[0] + iOBMCAlphaV * iCv[0] + iOBMCAlphaD * iCd[0] + iOBMCAlphaCt * iCct[0])/255;
			iOBMCP[1] = (iOBMCAlphaH * iPh[1] + iOBMCAlphaV * iPv[1] + iOBMCAlphaD * iPd[1] + iOBMCAlphaCt * iPct[1])/255;
			iOBMCC[1] = (iOBMCAlphaH * iCh[1] + iOBMCAlphaV * iCv[1] + iOBMCAlphaD * iCd[1] + iOBMCAlphaCt * iCct[1])/255;
			iOBMCP[2] = (iOBMCAlphaH * iPh[2] + iOBMCAlphaV * iPv[2] + iOBMCAlphaD * iPd[2] + iOBMCAlphaCt * iPct[2])/255;
			iOBMCC[2] = (iOBMCAlphaH * iCh[2] + iOBMCAlphaV * iCv[2] + iOBMCAlphaD * iCd[2] + iOBMCAlphaCt * iCct[2])/255;
			

			iP[0] = iRefine ? iPrf[0] : iOBMCP[0];  iP[1] = iRefine ? iPrf[1] : iOBMCP[1];  iP[2] = iRefine ? iPrf[2] : iOBMCP[2];
			iC[0] = iRefine ? iCrf[0] : iOBMCC[0];  iC[1] = iRefine ? iCrf[1] : iOBMCC[1];  iC[2] = iRefine ? iCrf[2] : iOBMCC[2];
			
			//dehalo replacement
			if(pMCParam->cuc_en)
			{
				if(iDehaloAlpha > 0) //uncover
				{
					iP[0] = (iC[0] * iDehaloAlpha + iP[0]*(16-iDehaloAlpha))>>4;
					iP[1] = (iC[1] * iDehaloAlpha + iP[1]*(16-iDehaloAlpha))>>4;
					iP[2] = (iC[2] * iDehaloAlpha + iP[2]*(16-iDehaloAlpha))>>4;
				}
				else if(iDehaloAlpha < 0)//cover
				{
					iC[0] = (-iP[0] * iDehaloAlpha + iC[0]*(16+iDehaloAlpha))>>4;
					iC[1] = (-iP[1] * iDehaloAlpha + iC[1]*(16+iDehaloAlpha))>>4;
					iC[2] = (-iP[2] * iDehaloAlpha + iC[2]*(16+iDehaloAlpha))>>4;
				}
			}

			//temp interp
			iPC[0]= (iP[0] * (128-pMCParam->temp_phase) + iC[0] * pMCParam->temp_phase) >> 7;
			iPC[1]= (iP[1] * (128-pMCParam->temp_phase) + iC[1] * pMCParam->temp_phase) >> 7;
			iPC[2]= (iP[2] * (128-pMCParam->temp_phase) + iC[2] * pMCParam->temp_phase) >> 7;

			iPC0[0]= (iP0[0] * (128-pMCParam->temp_phase) + iC0[0] * pMCParam->temp_phase) >> 7;
			iPC0[1]= (iP0[1] * (128-pMCParam->temp_phase) + iC0[1] * pMCParam->temp_phase) >> 7;
			iPC0[2]= (iP0[2] * (128-pMCParam->temp_phase) + iC0[2] * pMCParam->temp_phase) >> 7;


			//med3
			iM3v[0] = i16med3(iPC0[0], iP[0], iC[0], &iIdx);
			iM3v[1] = (iIdx==0)? iPC0[1] : (iIdx==1) ? iP[1] : iC[1];
			iM3v[2] = (iIdx==0)? iPC0[2] : (iIdx==1) ? iP[2] : iC[2];

			iM3v0[0] = i16med3(iPC[0], iP0[0], iC0[0], &iIdx);
			iM3v0[1] = (iIdx==0)? iPC[1] : (iIdx==1) ? iP0[1] : iC0[1];
			iM3v0[2] = (iIdx==0)? iPC[2] : (iIdx==1) ? iP0[2] : iC0[2];


			//vec spatial consistency blend, refine area using pc. others using med3(p,c,pc)
			if(pMCParam->good_prot_en)
			{
				iMux[0] = iRefine? iPC[0] : iM3v[0];
				iMux[1] = iRefine? iPC[1] : iM3v[1];
				iMux[2] = iRefine? iPC[2] : iM3v[2];
			}

			//bad area blend
			if(pMCParam->bad_prot_en)
			{
				iBBad[0] = (iMux[0] * (16 - iBadAlpha) + iM3v0[0] * iBadAlpha) >> 4;
				iBBad[1] = (iMux[1] * (16 - iBadAlpha) + iM3v0[1] * iBadAlpha) >> 4;
				iBBad[2] = (iMux[2] * (16 - iBadAlpha) + iM3v0[2] * iBadAlpha) >> 4;
			}

			//logo blend
			if((iLogoAlpha > 0) && pMCParam->logo_en)
			{
				iBLogo[0] = (iBBad[0] * (16 - iLogoAlpha) + iPC0[0] * iLogoAlpha ) >> 4; 
				iBLogo[1] = (iBBad[1] * (16 - iLogoAlpha) + iPC0[1] * iLogoAlpha ) >> 4; 
				iBLogo[2] = (iBBad[2] * (16 - iLogoAlpha) + iPC0[2] * iLogoAlpha ) >> 4; 
			}

			//output mux
			//out_sel //0: (p+c)/2;  1: P; 2:C; 3:(p0+c0)/2; 4:P0; 5:C0; 6: med(p,c,pc0) 7: med(p0,c0,pc)
			//output selector
			for(iChIdx=0; iChIdx<3; iChIdx++)
			{
				iPicOut[iChIdx] = (pMCParam->out_sel == 0) ? iPC[iChIdx] : 
				                  (pMCParam->out_sel == 1) ? iP[iChIdx] : 
						  		  (pMCParam->out_sel == 2) ? iC[iChIdx] :
								  (pMCParam->out_sel == 3) ? iPC0[iChIdx]:
								  (pMCParam->out_sel == 4) ? iP0[iChIdx]:
								  (pMCParam->out_sel == 5) ? iC0[iChIdx] : 
								  (pMCParam->out_sel == 6) ? iM3v[iChIdx] :
								  (pMCParam->out_sel == 7) ? iM3v0[iChIdx] : 
								  (pMCParam->out_sel == 8) ? iMux[iChIdx] :
								  (pMCParam->out_sel == 9) ? iBBad[iChIdx] :
								  (pMCParam->out_sel == 10)? iBLogo[iChIdx] :
								  iPC[iChIdx] ;
			    
			}

			//out overlay
			//y_overlay_mode, 0: no overlay ; 1: SAD in Y;  2: Active in Y; 4: vector size in Y  5:|vx| in Y  6: |vy| in Y  7: logo alpha in Y; 8:OOB in Y; 9:
			switch(pMCParam->y_overlay_mode)
			{
			case 0 : iYol = iPicOut[0];
			//case 1 : iYol = pMCParam->iSad;
			//case 2 : iYol = pMCParam->iDetail;
			case 4 : iYol = i16abs(iVecCt[0]) + i16abs(iVecCt[1]);
			case 5 : iYol = i16abs(iVecCt[0]);
			case 6 : iYol = i16abs(iVecCt[1]);
			case 7 : iYol = iLogoAlpha;
			case 8 : iYol = iBadAlpha;
			case 9 : iYol = iRefine;
			default: iYol = iPicOut[0];
			}


			//uv_overlay_mode, 0: no overlay ; 1: 128;  2: idx mode; 4: vx in u and vy in v  5:vx in Y  6: vy in Y  7: 

			switch(pMCParam->uv_overlay_mode)
			{
			case 0 : iUol = iPicOut[1];iVol = iPicOut[2];
			case 1 : iUol = 128;iVol = 128;
			//case 2 : iUol = iUIdx; iVol = iVIdx;
			case 4 : iUol = iVecCt[0]*pMCParam->ol_ku + 128; iVol = iVecCt[1]*pMCParam->ol_kv + 128;
			case 5 : iUol = iVecCt[0]*pMCParam->ol_ku + 128; iVol = 128;
			case 6 : iUol = 128;iVol = iVecCt[1]*pMCParam->ol_kv + 128;
			case 7 : iUol = iLogoAlpha * pMCParam->ol_ku + 128; iVol = iLogoAlpha * pMCParam->ol_kv + 128;
			case 8 : iUol = iBadAlpha * pMCParam->ol_ku + 128; iVol = iBadAlpha * pMCParam->ol_kv + 128;
			case 9 : iUol = iRefine *  pMCParam->ol_ku + 128; iVol = iRefine *  pMCParam->ol_kv + 128;
			default: iUol = iPicOut[1];iVol = iPicOut[2];
			}

			//saturate
			iMCOut[0] = (UINT8) iYol>255? 255 : iYol<0? 0 : iYol;
			iMCOut[1] = (UINT8) iUol>255? 255 : iUol<0? 0 : iUol;
			iMCOut[2] = (UINT8) iVol>255? 255 : iVol<0? 0 : iVol;
			//grid_en
			if(pMCParam->grid_en)
			{
				if(((iPicIdx[0] %pMCParam->block_size[0]) == 0) || ((iPicIdx[1] %pMCParam->block_size[1]) == 0))
					iMCOut[0] = 0; iMCOut[1] = 128; iMCOut[2] = 128;
			}
			

			for(iChIdx=0; iChIdx<3; iChIdx++)
				pYUV[iPicIdx[0]+iPicIdx[1]*iPicSize[0]+iPicSize[0]*iPicSize[1]*iChIdx] = iMCOut[iChIdx];


			
		}

}

void        mc(const UINT8* pPreYUV, const UINT16* pPreSize, int iPrePolarity, 
               const UINT8* pCurYUV, const UINT16* pCurSize, int iCurPolarity,  
               const T_MC_PARAM* pMCParam,
               UINT8* pYUV, int* pOutSize)
{
	UINT8*  pOBMCAlpha;
	INT16*  pOBMCVec;
	UINT8*  pRefineMask;
	INT8*   pLogohitMask;
	UINT8*  pLogoAlpha;
	INT8*   pOOBMask;
	INT8*   pDehaloAlpha;
	UINT8*  pBadAlpha;

	pOBMCAlpha   = (UINT8*) malloc(pOutSize[0]*pOutSize[1]  *4*sizeof(UINT8));   //4 per pixel
	pOBMCVec     = (INT16*) malloc(pOutSize[0]*pOutSize[1]*2*4*sizeof(INT16));   //4 per pixel
	pRefineMask  = (UINT8*) malloc(pOutSize[0]*pOutSize[1]    *sizeof(UINT8));   //1 per pixel
	pLogohitMask = (INT8*)  malloc(pOutSize[0]*pOutSize[1]  *4*sizeof(INT8));    //4 per pixel
	pLogoAlpha   = (UINT8*) malloc(pOutSize[0]*pOutSize[1]   *sizeof(UINT8));    //1 per pixel
	pOOBMask     = (INT8*)  malloc(pOutSize[0]*pOutSize[1]  *4*sizeof(INT8));    //4 per pixel
	pBadAlpha    = (UINT8*) malloc(pOutSize[0]*pOutSize[1]   *sizeof(UINT8));    //1 per pixel
	pDehaloAlpha = (INT8*)  malloc(pOutSize[0]*pOutSize[1]    *sizeof(INT8));    //1 per pixel


	//
    get_masks(pMCParam, pOBMCAlpha, pOBMCVec, pRefineMask, pLogohitMask, pLogoAlpha, pOOBMask, pDehaloAlpha, pBadAlpha, pOutSize);    //get obmc vectors plans and alpha plans

    get_picture(pPreYUV, pPreSize, iPrePolarity,
		         pCurYUV, pCurSize, iCurPolarity,
				 pMCParam,
				 pOBMCAlpha, (const INT16*) pOBMCVec, pRefineMask, pLogohitMask, pLogoAlpha, pOOBMask, pDehaloAlpha,pBadAlpha,
				 pYUV, pOutSize);      //get picture
	free(pOBMCAlpha); free(pOBMCVec); free(pRefineMask); free(pLogohitMask); free(pLogoAlpha);
	free(pOOBMask); free(pBadAlpha); free(pDehaloAlpha);
}

mxArray *  call_mc( const UINT8* pCurYUV, const UINT16* pCurSize, int iCurPolarity, 
                    const UINT8* pPreYUV, const UINT16* pPreSize, int iPrePolarity,  
                    const mxArray* pmxaMCParam)
{
    mxArray*    pResult;

	UINT8*      pYUV;
	int         pPicDims[3];
    
    T_MC_PARAM  tMCParam;
    
    //get 3DRS parameter
    parser_mc_parameter(&tMCParam, pmxaMCParam);
    
	//get output picture size
	pPicDims[0] = pCurSize[0];
	if(iCurPolarity == FRM_PARITY_PROGRESS)
		pPicDims[1] = pCurSize[1];
	else
		pPicDims[1] = pCurSize[1]*2;
	pPicDims[2]     = 3;

	//create output structure
	pResult  = mxCreateNumericArray(3, (const mwSize*)pPicDims, mxUINT8_CLASS, mxREAL);
	pYUV     = (UINT8*) mxGetData(pResult);


    mc(pPreYUV, pPreSize, iPrePolarity, 
       pCurYUV, pCurSize, iCurPolarity,  
       &tMCParam, 
       pYUV, pPicDims);
   
	return pResult;
}



/* mex file interface */
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray* prhs[] )
{

	const UINT8                  *pCurYUV, *pPreYUV;
	T_FRM_PARITY                iCurPolarity, iPrePolarity;
	UINT16                         iCurSize[2], iPreSize[2];
    const int*                  pTmpI;

	const mxArray*       pMCParam;
	

    if (nrhs != 5) { 
		mexErrMsgTxt("mc need 5 input parameters."); 
    }
	else if (nlhs != 1) {
		mexErrMsgTxt("mc need 1 output arguments."); 
    } 
	
	/*check and get common parameters*/

	//picture data
    pCurYUV         =    (UINT8*)  mxGetData(CURRENT_YUV);
    pTmpI             =  (const int *) mxGetDimensions(CURRENT_YUV);
    iCurSize[0]      =              pTmpI[0];
    iCurSize[1]      =              pTmpI[1];
    iCurPolarity     =   *((UINT8*) mxGetData(CUR_POLARITY));
    
    pPreYUV         =    (UINT8*)  mxGetData(PREVIOUS_YUV);
    pTmpI            =   (const int *) mxGetDimensions(PREVIOUS_YUV);
    iPreSize[0]      =              (UINT16)pTmpI[0];
    iPreSize[1]      =              (UINT16)pTmpI[1];
    iPrePolarity     =   *((UINT8*) mxGetData(PRE_POLARITY));

    pMCParam        =               MC_PARAMETER;

	verify_common_parameters( iCurSize, iCurPolarity,
	                          iPreSize, iPrePolarity);

	MC_RESULT = call_mc( pCurYUV, iCurSize, iCurPolarity, 
		     pPreYUV, iPreSize, iPrePolarity, pMCParam);
		                   
  	return;
}

